package com.autonavi.yunda.yunji.common.utils.clock;

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.Days;
import org.joda.time.format.DateTimeFormat;

import java.time.DayOfWeek;

/**
 * @author cizhong.wcs
 * @date 2022/1/25 3:46 下午
 */
public class AmapClock {
    public static final String DATE_FORMAT = "yyyyMMdd";
    public static final String MONTH_FORMAT = "yyyyMM";
    public static final String DATE_FORMAT_CHINESE = "yyyy年MM月dd日";
    public static final String BIRTHDAY_FORMAT = "MMdd";
    public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DATE_TIME_FORMAT_CHINESE = "yyyy年MM月dd日 HH:mm:ss";
    public static final Long MILLS_PER_HOUR = 3600000L;
    public static final Long MILLS_PER_DAY = 86400000L;
    public static final Long MILLS_PER_MONTH = 2592000000L;

    public static DateTimeZone getTimeZone() {
        return DateTimeZone.getDefault();
    }

    public static DateTime nowDate() {
        return new DateTime(getTimeZone());
    }

    public static DateTime date(Long timestamp) {
        return new DateTime(timestamp, getTimeZone());
    }

    public static Long dateStringToLong(String dateStr, String format) {
        return DateTimeFormat.forPattern(format).withZone(getTimeZone()).parseDateTime(dateStr).getMillis();
    }

    public static Long dateStringToLong(String dateStr) {
        return DateTimeFormat.forPattern(DATE_FORMAT).withZone(getTimeZone()).parseDateTime(dateStr).getMillis();
    }

    public static String dateStringFromTimestamp(Long timestamp) {
        return dateTimeStringFromTimestamp(timestamp, DATE_FORMAT);
    }

    public static String dateTimeStringFromTimestamp(Long timestamp) {
        return dateTimeStringFromTimestamp(timestamp, DATE_TIME_FORMAT);
    }

    public static String dateTimeStringFromTimestamp(Long timestamp, String format) {
        return null == timestamp ? null : date(timestamp).toString(DateTimeFormat.forPattern(format));
    }

    public static long now() {
        return nowDate().getMillis();
    }

    public static long nowDateInMillsWithHour(int hour) {
        return nowDate().withHourOfDay(hour).withMinuteOfHour(0).withSecondOfMinute(0).withMillisOfSecond(0).getMillis();
    }

    public static long nowDateInMillis() {
        return nowDate().withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0).withMillisOfSecond(0).getMillis();
    }

    public static long nowMonthInMillis() {
        return nowDate().withDayOfMonth(1).withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0).withMillisOfSecond(0).getMillis();
    }

    public static long getMinMillisOfDay(Long millis) {
        return date(millis).millisOfDay().withMinimumValue().getMillis();
    }

    public static long getMaxMillisOfDay(Long millis) {
        return date(millis).millisOfDay().withMaximumValue().getMillis();
    }

    public static long getMinMillisOfMonth(Long timestamp) {
        return getMinMillisOfDay((new DateTime(timestamp, getTimeZone())).withDayOfMonth(1).getMillis());
    }

    public static long getMaxMillisOfMonth(Long timestamp) {
        return getMaxMillisOfDay((new DateTime(timestamp, getTimeZone())).plusMonths(1).withDayOfMonth(1).minusDays(1).getMillis());
    }

    public static long getRemainingMillisOfMonth() {
        return getMaxMillisOfMonth(now()) - now();
    }

    public static long getRemainingMillisOfDay() {
        return getMaxMillisOfDay(now()) - now();
    }

    public static int getDaysBetween(Long startMillis, Long endMills) {
        return Days.daysBetween(date(startMillis), date(endMills)).getDays() + 1;
    }

    public static long hoursAgoInMills(int hoursAgo) {
        return now() - MILLS_PER_HOUR * (long) hoursAgo;
    }

    public static long daysAgoInMillis(int daysAgo) {
        return nowDateInMillis() - MILLS_PER_DAY * (long) daysAgo;
    }

    public static long monthsAgoInMills(int monthsAgo) {
        return nowDateInMillis() - MILLS_PER_MONTH * (long) monthsAgo;
    }

    public static long daysAfterInMills(int afterDays) {
        return nowDateInMillis() + MILLS_PER_DAY * (long) afterDays;
    }

    public static long daysAfterInMills(Long timeStamp, int afterDays) {
        return timeStamp + MILLS_PER_DAY * (long) afterDays;
    }

    public static long timeHoursAgoInMills(long time, int hoursAgo) {
        return time - MILLS_PER_HOUR * (long) hoursAgo;
    }

    public static long timeHoursAfterInMills(long time, int hoursAfter) {
        return time + MILLS_PER_HOUR * (long) hoursAfter;
    }

    public static boolean isWeekDay(Long timestamp) {
        int dayOfWeek = date(timestamp).getDayOfWeek();
        return dayOfWeek != DayOfWeek.SATURDAY.getValue() && dayOfWeek != DayOfWeek.SUNDAY.getValue();
    }
}
